package com.hui.config.security.access.vote;

import com.hui.config.security.core.authority.UrlGrantedAuthority;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.Iterator;

public class MyAccessDecisionManager implements AccessDecisionManager {

    /**
     * 用来判断url是否有权限,不抛异常就通过
     *
     * @apiNote 参考网址：http://www.jb51.net/article/105428.htm
     * @apiNote 登录请求不会进入方法进行投票
     */
    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        //这段代码其实不需要,因为spring-security-core-4.1.4.RELEASE-sources.jar!/org/springframework/security/access/intercept/AbstractSecurityInterceptor.java第215行判断提前返回了,不会进入decide方法
        if (CollectionUtils.isEmpty(configAttributes)) {
            throw new AccessDeniedException("not allow");
        }
        Collection<UrlGrantedAuthority> authorities = (Collection<UrlGrantedAuthority>) authentication.getAuthorities();
        Iterator<ConfigAttribute> ite = configAttributes.iterator();
        while (ite.hasNext()) {
            String url = (ite.next()).getAttribute();
            Iterator<UrlGrantedAuthority> iterator = authorities.iterator();
            while (iterator.hasNext()) {
                UrlGrantedAuthority authority = iterator.next();
                String strAuthority = authority.getAuthority();
                if (strAuthority.equals(url)) {
                    return;
                }
            }
        }
        //该url有配置权限,但是当然登录用户没有匹配到对应权限,则禁止访问
        throw new AccessDeniedException("not allow");//拒绝访问异常
    }

    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
}
